package com.ytc.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.ytc.commons.model.dto.CoursePubIndexDto;
import com.ytc.commons.model.dto.PageRequest;
import com.ytc.commons.model.vo.CoursePubIndexVo;
import com.ytc.commons.model.vo.CoursePubVo;
import com.ytc.commons.model.vo.PageResponseResult;
import com.ytc.commons.model.vo.ResponseResult;
import com.ytc.commons.utils.BeanHelper;
import com.ytc.content.api.ContentClient;
import com.ytc.search.domain.CoursePubIndex;
import com.ytc.search.service.SearchService;
import org.apache.tomcat.util.json.JSONParser;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    //课程搜索es
    @Override
    public PageResponseResult<CoursePubIndexVo> search(CoursePubIndexDto dto, PageRequest request)throws Exception {
        //1.构建查询条件
         //1.1创建SearchReuqest对象
        SearchRequest searchRequest = new SearchRequest("course");
         //1.2创建查询条件
        SearchSourceBuilder builder  = new SearchSourceBuilder();
        //分页参数
        builder.from((request.getPageNo()-1)*10);
        builder.size(request.getPageSize());

         //bool条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        String keyword = dto.getKeyword();//搜索关键字
        if(StringUtils.isEmpty(keyword)){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else {
            boolQuery.must(QueryBuilders.matchQuery("all",keyword));
        }
        //添加筛选条件三级分类
         String mt = dto.getMt();
        if (!StringUtils.isEmpty(mt)) {
            boolQuery.filter(QueryBuilders.termQuery("mt",mt));
        }
        String st = dto.getSt();
        if (!StringUtils.isEmpty(st)) {
            boolQuery.filter(QueryBuilders.termQuery("st",st));
        }
        //难度等级
        String grade = dto.getGrade();
        if (!StringUtils.isEmpty(grade)) {
            boolQuery.filter(QueryBuilders.termQuery("grade",grade));
        }
        builder.query(boolQuery);

        //设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color=red>").postTags("</font>")
                .field("name").requireFieldMatch(false);

        builder.highlighter(highlightBuilder);


        //1.3将查询条件，设置到searchRequest中
        searchRequest.source(builder);
        //2.发起请求
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //3.解析数据结果
          //总数response->hits->tatal
        SearchHits hits = response.getHits();
           Long total = hits.getTotalHits().value;
          //list集合: response->hits->hits数组->sourse（对象json字符串）
        SearchHit[] hitsHits = hits.getHits();
        List<CoursePubIndexVo> vos = new ArrayList<>();
        for(SearchHit hitHit : hitsHits){
            String json = hitHit.getSourceAsString();
            CoursePubIndex index = JSON.parseObject(json,CoursePubIndex.class);
            //将高亮部分的HighLight数据替换到index的name属性

            Map<String, HighlightField> map = hitHit.getHighlightFields();

            if(map!=null&&map.containsKey("name")){
                HighlightField nameField = map.get("name");
                String name = nameField.fragments()[0].toString();
                index.setName(name);
            }

            //将es对象转成vo
            CoursePubIndexVo vo = BeanHelper.copyProperties(index,CoursePubIndexVo.class);
            vo.setIndexId(index.getId());
            vos.add(vo);
        }
        //4.返回
        return new PageResponseResult(total,vos);

    }

    @Autowired
    private ContentClient contentClient;

    //同步更新索引
    @Override
    public void updateIndex(Long coursePubId) throws Exception{
        //1.调用feign接口，根据id查询课程发布对象，CoursePubVo
        ResponseResult<CoursePubVo> result = contentClient.findById(coursePubId);
        CoursePubVo vo = result.getData();
        //创建indexRequest对象
        IndexRequest indexRequest = new IndexRequest("course");
        //设置id，保存JSON数据
        indexRequest.id(vo.getId().toString());
        CoursePubIndex index = BeanHelper.copyProperties(vo,CoursePubIndex.class);
        index.setCompany_id(vo.getCompanyId());
        index.setCompany_name(vo.getCompanyName());
        index.setCourse_id(vo.getCourseId());

        indexRequest.source(JSON.toJSONString(index), XContentType.JSON);
        //调用client
        restHighLevelClient.index(indexRequest,RequestOptions.DEFAULT);
    }

    //根据id查询课程发布数据
    @Override
    public ResponseResult<CoursePubIndexVo> findById(Long id) throws Exception{
        //构造GetRequest请求
        GetRequest request = new GetRequest("course",id.toString());
        //发送请求
        GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
        //解析响应
        String json = response.getSourceAsString();
        //转化CoursePubIndex
        CoursePubIndex index = JSON.parseObject(json, CoursePubIndex.class);
        CoursePubIndexVo vo = BeanHelper.copyProperties(index, CoursePubIndexVo.class);
        //vo中需要的indexId，es对象中叫做id
        vo.setIndexId(index.getId());
        return ResponseResult.okResult(vo);
    }


}
